home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 22
/
Aminet 22 (1997)(GTI - Schatztruhe)[!][Dec 1997].iso
/
Aminet
/
util
/
cdity
/
cgxdpms.lha
/
CGXDPMS.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-10-08
|
14KB
|
760 lines
#include <clib/alib_protos.h>
#include <cybergraphics/cybergraphics.h>
#include <exec/execbase.h>
#include <exec/memory.h>
#include <intuition/intuitionbase.h>
#include <proto/commodities.h>
#include <proto/cybergraphics.h>
#include <proto/dos.h>
#include <proto/exec.h>
#include <proto/intuition.h>
#include <proto/icon.h>
#include <workbench/startup.h>
#include <string.h>
/* Compiler specific stuff. */
#define SAVEDS __saveds
#define ASM __asm
#define REG(x) register __ ## x
#define STKARGS __stdargs
#define VERSION "1.2"
#define DATE "9.10.97"
/* ----- Global variables ------------------------------------------------- */
struct Library *CxBase;
struct Library *CyberGfxBase;
struct DosLibrary *DOSBase;
struct Library *IconBase;
struct IntuitionBase *IntuitionBase;
struct ExecBase *SysBase;
struct MsgPort *CxPort;
struct WBStartup *WBMsg;
CxObj *Broker;
CxObj *Sender;
CxObj *Custom;
LONG StandbyTime;
LONG SuspendTime;
LONG OffTime;
LONG IETime;
LONG StandbyCounter;
LONG SuspendCounter;
LONG OffCounter;
LONG SendShift;
LONG NoMouse;
LONG State;
LONG FinalState;
struct InputEvent ShiftDown;
struct InputEvent ShiftUp;
TEXT BlankKey[ 128 ];
#define DEF_CXPRI 1
#define DEF_STANDBY 20
#define DEF_SUSPEND 20
#define DEF_OFF 20
#define DEF_SENDSHIFT 1
#define ID_SENDER 1
#define ID_CUSTOM 2
#define ID_BLANK 3
/* Don't know if this is a good value for ie.dead... They key code
* should be for a non-existant key. Oh well, doesn't cause Enforcer
* hits for me at least. ;)
*/
#define MAGIC ( APTR ) 81008100L
struct Args
{
LONG *CxPriority;
STRPTR BlankKey;
LONG *StandbyTime;
LONG *SuspendTime;
LONG *OffTime;
LONG *ShiftTime;
LONG SendShift;
LONG NoMouse;
};
#define TEMPLATE "CX_PRIORITY/K/N,BLANKKEY/K,STANDBYTIME/K/N,SUSPENDTIME/K/N,OFFTIME/K/N,SHIFTTIME/K/N,SENDSHIFT/S,NOMOUSE/S"
/* ----- Startup code ----------------------------------------------------- */
static LONG Main( VOID );
LONG SAVEDS
Startup( VOID )
{
LONG r = 100;
SysBase = *( ( struct ExecBase ** ) 4 );
{
struct Process *thisTask = ( struct Process * ) FindTask( NULL );
if( !thisTask->pr_CLI )
{
/* Handle Workbench startup message */
struct MsgPort *port = &thisTask->pr_MsgPort;
WaitPort( port );
WBMsg = ( struct WBStartup * ) GetMsg( port );
}
}
SetSignal( 0, SIGBREAKF_CTRL_C );
if( SysBase->LibNode.lib_Version >= 37 )
{
r = Main();
}
if( WBMsg )
{
Forbid();
ReplyMsg( ( struct Message * ) WBMsg );
}
return( r );
}
struct NewBroker NewBroker =
{
NB_VERSION,
"CGXDPMS",
"CGXDPMS " VERSION " by Magnus Holmgren",
"DPMS manager for CyberGraphX",
NBU_UNIQUE, 0, 0,
NULL, 0
};
static const TEXT Ver[] = "$VER: CGXDPMS " VERSION " (" DATE ")";
/* ----- Misc ------------------------------------------------------------- */
static LONG
MyRequestA( STRPTR title, STRPTR body, STRPTR gads, APTR args )
{
struct EasyStruct es;
es.es_StructSize = sizeof( es );
es.es_Flags = 0;
es.es_Title = title;
es.es_TextFormat = body;
es.es_GadgetFormat = gads;
return( EasyRequestArgs( NULL, &es, NULL, args ) );
}
static LONG
MyRequest( STRPTR title, STRPTR body, STRPTR gads, ... )
{
return( MyRequestA( title, body, gads, &gads + 1 ) );
}
static VOID
ErrRequest( STRPTR body, ... )
{
if( WBMsg )
{
MyRequestA( "CGXDPMS error message", body, "Quit", &body + 1 );
}
else
{
VPrintf( body, &body + 1 );
PutStr( "\n" );
}
}
/* ----- Libs ------------------------------------------------------------- */
static struct Library *
OpenLib( STRPTR name, LONG ver )
{
struct Library *lib;
if( !( lib = OpenLibrary( name, ver ) ) )
{
ErrRequest( "Couldn't open %s\nversion %ld or higher!", name, ver );
}
return( lib );
}
#define CloseLib(lib) CloseLibrary( ( struct Library * ) lib )
static VOID
CloseLibs( VOID )
{
if( DOSBase )
{
CloseLib( DOSBase );
CloseLib( IntuitionBase );
CloseLib( CyberGfxBase );
CloseLib( CxBase );
}
}
static LONG
OpenLibs( VOID )
{
LONG rc = FALSE;
if( DOSBase = ( struct DosLibrary * ) OpenLibrary( "dos.library", 37 ) )
{
if( IntuitionBase = ( struct IntuitionBase * ) OpenLibrary( "intuition.library", 37 ) )
{
if( ( CyberGfxBase = OpenLib( "cybergraphics.library", 40 ) )
&& ( CxBase = OpenLib( "commodities.library", 37 ) ) )
{
rc = TRUE;
}
}
}
return( rc );
}
/* ----- Argument parsing ------------------------------------------------- */
static VOID
GetBlankKey( STRPTR str )
{
if( str )
{
strncpy( BlankKey, str, sizeof( BlankKey ) - 1 );
}
}
static LONG
GetNumTT( struct DiskObject *icon, STRPTR name, LONG def )
{
STRPTR str;
LONG val;
val = def;
if( str = FindToolType( ( UBYTE ** ) icon->do_ToolTypes, name ) )
{
if( StrToLong( str, &val ) == -1 )
{
MyRequest( "CGXDMPS Warning", "Argument for %s should be numeric.\nUsing default (%ld).", "OK", name, def );
val = def;
}
}
return( val );
}
static LONG
GetTimeTT( struct DiskObject *icon, STRPTR name, LONG def )
{
/* return( SMult32( GetNumTT( icon, name, def ), 60 ) ); */
return( GetNumTT( icon, name, def ) * 60 );
}
static LONG
ParseWBArgs( VOID )
{
LONG rc = FALSE;
if( IconBase = OpenLib( "icon.library", 37 ) )
{
struct DiskObject *icon;
BPTR oldDir;
oldDir = CurrentDir( WBMsg->sm_ArgList[ 0 ].wa_Lock );
/* Lazy parsing: Ignore any multiselected icons... */
if( icon = GetDiskObject( WBMsg->sm_ArgList[ 0 ].wa_Name ) )
{
NewBroker.nb_Pri = GetNumTT( icon, "CX_PRIORITY", DEF_CXPRI );
GetBlankKey( FindToolType( ( UBYTE ** ) icon->do_ToolTypes, "BLANKKEY" ) );
StandbyTime = GetTimeTT( icon, "STANDBYTIME", DEF_STANDBY );
SuspendTime = GetTimeTT( icon, "SUSPENDTIME", DEF_SUSPEND );
OffTime = GetTimeTT( icon, "OFFTIME", DEF_OFF );
IETime = GetTimeTT( icon, "SHIFTTIME", DEF_SENDSHIFT );
SendShift = ( LONG ) FindToolType( ( UBYTE ** ) icon->do_ToolTypes, "SENDSHIFT" );
NoMouse = ( LONG ) FindToolType( ( UBYTE ** ) icon->do_ToolTypes, "NOMOUSE" );
rc = TRUE;
FreeDiskObject( icon );
}
else
{
ErrRequest( "Couldn't get program icon!" );
}
CurrentDir( oldDir );
CloseLibrary( IconBase );
}
else
{
ErrRequest( "Couldn't open icon.library\nversion 37 or higher!" );
}
return( rc );
}
static LONG
GetNum( LONG *val, LONG def )
{
LONG rc;
rc = def;
if( val )
{
rc = *val;
}
return( rc );
}
static LONG
GetTime( LONG *val, LONG def )
{
/* return( SMult32( GetNum( val, def ), 60 ) ); */
return( GetNum( val, def ) * 60 );
}
/* SAS/C insists on using in an optimized memset (that also is quite large)
* when compiling for a 68020+. Not what we want here, since we only want
* to clear less than 100 bytes *once*. So we have our own simple one
* instead.
*/
static VOID
ClrMem( UBYTE *buf, LONG size )
{
do
{
*buf++ = 0;
}
while( --size );
}
static LONG
ParseCLIArgs( VOID )
{
struct Args args;
struct RDArgs *rdarg;
LONG rc = FALSE;
ClrMem( ( UBYTE * ) &args, sizeof( args ) );
if( rdarg = ReadArgs( TEMPLATE, ( LONG * ) &args, NULL ) )
{
NewBroker.nb_Pri = GetNum( args.CxPriority, DEF_CXPRI );
GetBlankKey( args.BlankKey );
StandbyTime = GetTime( args.StandbyTime, DEF_STANDBY );
SuspendTime = GetTime( args.SuspendTime, DEF_SUSPEND );
OffTime = GetTime( args.OffTime, DEF_OFF );
IETime = GetTime( args.ShiftTime, DEF_SENDSHIFT );
SendShift = args.SendShift;
NoMouse = args.NoMouse;
rc = TRUE;
FreeArgs( rdarg );
}
return( rc );
}
static LONG
ParseArgs( VOID )
{
return( ( LONG ) ( WBMsg ? ParseWBArgs() : ParseCLIArgs() ) );
}
/* ----- Commodity support ------------------------------------------------ */
static VOID
Unblank( CxMsg *msg )
{
StandbyCounter = StandbyTime;
SuspendCounter = SuspendTime;
OffCounter = OffTime;
if( State != DPMS_ON )
{
State = DPMS_ON;
RouteCxMsg( msg, Sender );
}
}
/* This function runs on the input.device task context. Thus, we need to
* set smalldata base, make sure we don't call any nasty functions, and
* generally try to do our job quickly.
*/
static STKARGS VOID SAVEDS
CxCustomFunc( register CxMsg *msg, CxObj *obj )
{
struct InputEvent *ie;
static LONG LastSecs, LastIE;
LONG diff;
ie = ( struct InputEvent * ) CxMsgData( msg );
switch( ie->ie_Class )
{
case IECLASS_RAWMOUSE:
case IECLASS_POINTERPOS:
case IECLASS_NEWPOINTERPOS:
/* Ignore mouse movements while blanked? */
if( !( NoMouse && ( State != DPMS_ON ) && ( ie->ie_Code == IECODE_NOBUTTON ) ) )
{
Unblank( msg );
}
break;
case IECLASS_RAWKEY:
/* Ignore rawkeys we send out, as well as key releases
* (to make the hotkey possible).
*/
if( !( ( ie->ie_position.ie_addr == MAGIC ) || ( ie->ie_Code & IECODE_UP_PREFIX ) ) )
{
Unblank( msg );
}
break;
case IECLASS_DISKREMOVED:
case IECLASS_DISKINSERTED:
Unblank( msg );
break;
case IECLASS_TIMER:
diff = ie->ie_TimeStamp.tv_secs - LastSecs;
/* Check for blanking at most once per second, if needed */
if( ( diff > 0 ) && ( State != FinalState ) && LastSecs )
{
if( ( State < DPMS_STANDBY ) && ( StandbyCounter > 0 ) )
{
StandbyCounter -= diff;
if( StandbyCounter <= 0 )
{
State = DPMS_STANDBY;
RouteCxMsg( msg, Sender );
}
}
else if( ( State < DPMS_SUSPEND ) && ( SuspendCounter > 0 ) )
{
SuspendCounter -= diff;
if( SuspendCounter <= 0 )
{
State = DPMS_SUSPEND;
RouteCxMsg( msg, Sender );
}
}
else if( ( State < DPMS_OFF ) && ( OffCounter > 0 ) )
{
OffCounter -= diff;
if( OffCounter <= 0 )
{
State = DPMS_OFF;
RouteCxMsg( msg, Sender );
}
}
if( SendShift && ( State != DPMS_ON ) )
{
diff = ie->ie_TimeStamp.tv_secs - LastIE;
if( diff > IETime )
{
LastIE = ie->ie_TimeStamp.tv_secs;
ShiftDown.ie_TimeStamp = ie->ie_TimeStamp;
ShiftUp.ie_TimeStamp = ie->ie_TimeStamp;
/* Hm.. Maybe this would be better to do on the
* main process' context. Oh well, not called
* often anyway. At most once per minute. ;)
*/
AddIEvents( &ShiftDown );
}
}
}
LastSecs = ie->ie_TimeStamp.tv_secs;
break;
}
}
static VOID
FreeBroker( VOID )
{
DeleteCxObjAll( Broker );
DeleteMsgPort( CxPort );
}
static LONG
InitBroker( VOID )
{
LONG rc = FALSE;
ShiftUp.ie_Class = ShiftDown.ie_Class = IECLASS_RAWKEY;
ShiftDown.ie_Code = 0x60, /* Shift (Left, I think) */
ShiftUp.ie_Code = IECODE_UP_PREFIX | 0x60;
ShiftUp.ie_position.ie_addr = ShiftDown.ie_position.ie_addr = MAGIC;
ShiftDown.ie_NextEvent = &ShiftUp;
StandbyCounter = StandbyTime;
SuspendCounter = SuspendTime;
OffCounter = OffTime;
State = DPMS_ON;
if( StandbyTime )
{
FinalState = DPMS_STANDBY;
}
if( SuspendTime )
{
FinalState = DPMS_SUSPEND;
}
if( OffTime )
{
FinalState = DPMS_OFF;
}
if( CxPort = NewBroker.nb_Port = CreateMsgPort() )
{
LONG err;
if( Broker = CxBroker( &NewBroker, &err ) )
{
if( *BlankKey )
{
AttachCxObj( Broker, HotKey( BlankKey, CxPort, ID_BLANK ) );
}
AttachCxObj( Broker, Custom = CxCustom( CxCustomFunc, ID_CUSTOM ) );
AttachCxObj( Custom, Sender = CxSender( CxPort, ID_SENDER ) );
if( CxObjError( Broker ) == COERR_BADFILTER )
{
ErrRequest( "Bad hotkey description for BLANKKEY!\n('%s')", BlankKey );
}
else if( CxObjError( Broker ) || CxObjError( Custom ) )
{
ErrRequest( "Not enough memory for Commodities objects!" );
}
else
{
rc = TRUE;
}
}
else if( err != CBERR_DUP )
{
ErrRequest( "Couldn't create broker!" );
}
}
else
{
ErrRequest( "Couldn't create message port!" );
}
if( !rc )
{
FreeBroker();
}
return( rc );
}
static VOID
HandleDPMS( VOID )
{
struct Screen *wb;
/* Configurable screen name? Maybe for a future version... */
if( wb = LockPubScreen( "Workbench" ) )
{
/* Passing args via globals isn't the best perhaps, but it works. ;) */
CVideoCtrlTags( &wb->ViewPort,
SETVC_DPMSLevel, State,
TAG_DONE );
UnlockPubScreen( NULL, wb );
}
}
static VOID
HandleKey( VOID )
{
if( State == DPMS_ON )
{
/* Maybe we should use Semaphores or something here to prevent
* any odd behaviour. Not that likely to happen though (I
* think ;), and even if it does happen, the effects are
* really minor (not going to the "right" state).
*/
if( StandbyTime )
{
StandbyCounter = 1;
}
else if( SuspendTime )
{
SuspendCounter = 1;
}
else if( OffTime )
{
OffCounter = 1;
}
}
}
static LONG
HandleCxPort( VOID )
{
CxMsg *msg;
LONG run = TRUE;
while( msg = ( CxMsg * ) GetMsg( CxPort ) )
{
LONG id, type;
id = CxMsgID( msg );
type = CxMsgType( msg );
ReplyMsg( ( struct Message * ) msg );
switch( type )
{
case CXM_IEVENT:
switch( id )
{
case ID_SENDER:
HandleDPMS();
break;
case ID_BLANK:
HandleKey();
break;
}
break;
case CXM_COMMAND:
switch( id )
{
case CXCMD_DISABLE:
ActivateCxObj( Broker, FALSE );
break;
case CXCMD_ENABLE:
ActivateCxObj( Broker, TRUE );
break;
case CXCMD_KILL:
run = FALSE;
break;
}
break;
}
}
return( run );
}
/* ----- Main program ----------------------------------------------------- */
static VOID
MainLoop( VOID )
{
LONG cxMask = 1 << CxPort->mp_SigBit;
ActivateCxObj( Broker, TRUE );
for( ;; )
{
LONG sigs;
sigs = Wait( cxMask | SIGBREAKF_CTRL_C );
if( sigs & cxMask )
{
if( !HandleCxPort() )
{
break;
}
}
if( sigs & SIGBREAKF_CTRL_C )
{
break;
}
}
}
static LONG
Main( VOID )
{
LONG ret = RETURN_FAIL;
if( OpenLibs() )
{
if( ParseArgs() )
{
if( InitBroker() )
{
MainLoop();
ret = RETURN_OK;
FreeBroker();
}
}
CloseLibs();
}
return( ret );
}